package log

import (
	"fmt"
	"os"
	"path/filepath"
	"sync"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
)

// 构建简单的日志输出结构
var Logger *zap.Logger
var onece = sync.Once{}

// 初始化zap日志
func Setup() {
	onece.Do(func() {
		Logger = zap.New(zapcore.NewCore(getEncoder(), getWriterSyncer(), zap.DebugLevel), zap.AddCaller(), zap.AddCallerSkip(1), zap.AddStacktrace(zap.ErrorLevel))
	})
}

// 暂时默认使用控制台输出格式
func getEncoder() zapcore.Encoder {
	conf := zapcore.EncoderConfig{
		TimeKey:        "ts",
		LevelKey:       "level",
		NameKey:        "logger",
		CallerKey:      "caller",
		FunctionKey:    zapcore.OmitKey,
		MessageKey:     "msg",
		StacktraceKey:  "stacktrace",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.LowercaseLevelEncoder,
		EncodeTime:     zapcore.ISO8601TimeEncoder,
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder,
	}
	return zapcore.NewConsoleEncoder(conf)
}

func Error(msg string, fields ...zap.Field) {
	Logger.Error(msg, fields...)
	//刷新
	Logger.Sync()
}

func Info(msg string, fields ...zap.Field) {
	Logger.Info(msg, fields...)
	//刷新
	Logger.Sync()
}

func Warn(msg string, fields ...zap.Field) {
	Logger.Warn(msg, fields...)
	//刷新
	Logger.Sync()
}

func Debug(msg string, fields ...zap.Field) {
	Logger.Debug(msg, fields...)
	//刷新
	Logger.Sync()
}

// 暂时使用直接文件输出
// @TODO 后面考虑使用lumberjack或者使用ratatelogs
func getWriterSyncer() zapcore.WriteSyncer {
	// file, err := os.OpenFile("log.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
	// if err != nil {
	// 	fmt.Println("日志文件打开失败")
	// 	panic(err)
	// }
	//获得工作目录
	exeurl := fmt.Sprintf("%s.log", os.Args[0])
	_, filename := filepath.Split(exeurl)
	lumberJackLogger := &lumberjack.Logger{
		Filename:   fmt.Sprintf("log/%s", filename), // 文件位置
		MaxSize:    50,                              // 进行切割之前,日志文件的最大大小(MB为单位)
		MaxAge:     1,                               // 保留旧文件的最大天数
		MaxBackups: 20,                              // 保留旧文件的最大个数
		Compress:   false,                           // 是否压缩/归档旧文件
	}
	multi := zapcore.NewMultiWriteSyncer(zapcore.AddSync(lumberJackLogger), zapcore.AddSync(os.Stdout))
	return multi
}
